<!--

    日期选择器picker，根据传进来的options显示特定的日期选择

    用法：<f7-date-picker
            :options="dateOptions"
            ref="pickerRef"
            :withMonth="false"
            @submit="pickerSearch"
          ></f7-date-picker>

          <f7-date-picker
          :options="dateOptions.zsj"
          ref="pickerRef2"
          :withMonth="true"
          @submit="pickerSearch"
        ></f7-date-picker>

    参数：
      options：显示的时间数组，表示可以选择的年份和月份；
        带年月的：[
            {key: "2020", value: [1,2,3]},
            {key: "2019", value: [1,2,3]},
            {key: "2018", value: [1,2,3]},
          ],
        只带年份的：[
          {key: "2020年度", value: 2020},
          {key: "2019年度", value: 2019},
          {key: "2018年度", value: 2018},
        ]

      withMonth: Boolean，是否显示月份；
      @submit：选择完成后触发的事件，方法参考
        pickerSearch(val) {
          // val 是数组，具体console.log看其值
        },
      optionKey：options数组里的每个对象的key字段名称，默认为key，表示年份；
      optionValue：options数组里的每个对象的value字段名称，默认为value，表示月份；
      withQuarter：是否将月份显示成季度，例如3月份为一季度，6月份为二季度等；

      sortKeyForYear：上面只带年份的options中根据哪个字段来排序，默认为value，withMonth为false时生效；
      sortKeyForYearMonth：上面带年月的的options中根据哪个字段来排序，默认为key，withMonth为true时生效；

    设置默认值：
      <f7-date-picker
          :options="dateOptionsEmpty"
          ref="pickerRef"
          :withMonth="true"
          :value="['2020', '5']"
          @submit="pickerSearch"
        ></f7-date-picker>
      或者
      <f7-date-picker
          :options="dateOptionsEmpty"
          ref="pickerRef2"
          :withMonth="false"
          :value="['2020']"
          @submit="pickerSearch"
        ></f7-date-picker>
 -->
<template>
  <input
    type="text"
    class="f7-date-picker"
    :placeholder="placeholder"
    :name="name"
    readonly
    :withMonth="withMonth"
    :required="required"
  />
</template>
<script>
export default {
  props: {
    // 需要显示年月日设置为true
    withDay: Boolean,
    // 需要显示年月日时间设置为true
    withTime: Boolean,
      // 隐藏单位显示  如果显示到时间的话 屏幕宽度不足导致内容不能完整显示出来
    hiddenUnits: Boolean,
    options: {
      type: Array,
      default: () => {
        return [];
      }
    },
    params: null,
    placeholder: String,
    name: String,
    optionKey: {
      type: String,
      default: "key"
    },
    optionValue: {
      type: String,
      default: "value"
    },
    value: [String, Number, Array],
    defaultDate: {
      type: Date,
      default: () => new Date()
    },
    displayValue: {
      type: Boolean,
      default: false
    },
    required: {
      type: Boolean,
      default: false
    },
    withMonth: {
      type: Boolean,
      default: false
    },
    withQuarter: {
      type: Boolean,
      default: false
    },
    startYear: {
      type: Number,
      default: 1900
    },
    endYear: {
      type: Number,
      default: 2100
    },
    sortKeyForYear: {
      type: String,
      default: "value"
    },
    sortKeyForYearMonth: {
      type: String,
      default: "key"
    },
    yearText: {
      type: String,
      default: '年'
    },
    monthText: {
      type: String,
      default: '月'
    },
    dayText: {
      type: String,
      default: "日"
    },
    hourText: {
      type: String,
      default: "时"
    },
    minuteText: {
      type: String,
      default: "分"
    },

  },
  data() {
    return {
      dateOptions: []
    };
  },
  watch: {
    value: function(val, old) {
      this.picker.setValue(this.$util.buildArray(val));
    }
  },
  methods: {
    validatePicker($el = this.$el) {
      let $pels = this.$$($el).find(".f7-picker input[required]");
      if ($pels && $pels.length > 0) {
        this.$util.each($pels, t => {
          const inst = t.f7Picker;
          const $inputEl = this.$$(t);
          const $itemInputEl = $inputEl.parents(".item-input");
          if (inst && (!inst.getValue() || inst.getValue().length == 0)) {
            const validationMessage =
              $inputEl.dataset().errorMessage ||
              t.validationMessage ||
              "请选择此字段。";
            let $errorEl = $inputEl.nextAll(".item-input-error-message");
            if (validationMessage) {
              if ($errorEl.length === 0) {
                $errorEl = this.$$(
                  '<div class="item-input-error-message"></div>'
                );
                $errorEl.insertAfter($inputEl);
              }
              $errorEl.text(validationMessage);
            }
            if ($errorEl.length > 0) {
              $itemInputEl.addClass("item-input-with-error-message");
            }
            $itemInputEl.addClass("item-input-invalid");
            $inputEl.addClass("input-invalid");
          } else {
            this.$$(t)
              .parents(".item-input")
              .removeClass("item-input-invalid item-input-with-error-message");
            this.$$(t).removeClass("input-invalid");
          }
        });
      }
      return this.$$($el).find(".item-input-invalid").length == 0;
    },
    toQuarter(m) {
      let quarters = ["一季度", "二季度", "三季度", "四季度"];
      return quarters[Math.ceil(m / 3) - 1];
    },
    init(opts) {
      if (this.withMonth) {
        // 排序
        this.dateOptions.sort((a, b) => {
          return b[this.sortKeyForYearMonth] - a[this.sortKeyForYearMonth];
        });
        let years = {
          textAlign: "right",
          values: [],
          width: "50%",
          displayValues: [],
          onChange: (picker, year) => {
            // 根据年来获取可用的月
            let find = this.$util.find(this.dateOptions, t => {
              return t.key == year;
            });
            if (find) {
              let ms = { values: [], displayValues: [] };

              this.$util.each(find[this.optionValue], m => {
                ms.values.push(m);
                ms.displayValues.push(
                  this.withQuarter ? this.toQuarter(m) : m + (this.hiddenUnits ? "" : this.monthText)
                );
              });
              if (picker.cols[1].replaceValues) {
                picker.cols[1].replaceValues(ms.values, ms.displayValues);
              }
            }
          }
        };
        let months = {
          textAlign: "left",
          values: [],
          displayValues: [],
          width: "50%"
        };

        this.$util.each(this.dateOptions, t => {
          if (this.$util.isString(t)) {
            months.values.push(t);
            months.displayValues.push(this.withQuarter ? this.toQuarter(t) : t);
          } else {
            years.values.push(t[this.optionKey]);
            years.displayValues.push(t[this.optionKey] + (this.hiddenUnits ? "" : this.yearText));
            // 默认值
            if (
              parseInt(t[this.optionKey]) === this.defaultDate.getFullYear()
            ) {
              months.values = t[this.optionValue];
              months.displayValues = [];
              this.$util.each(t[this.optionValue], m => {
                months.displayValues.push(
                  this.withQuarter ? this.toQuarter(m) : m + (this.hiddenUnits ? "" : this.monthText)
                );
              });
            }
          }
        });
        opts.cols = [years, months];
      } else if(this.withDay || this.withTime) {

        let years, months, days, hours, minutes;

        years = {
          textAlign: "center",
          values: (()=> {
            let arr = [];
            for (let i = this.startYear; i <= this.endYear; i++) {
              arr.push(i);
            }
            return arr;
          })(),
          displayValues: (()=> {
            let arr = [];
            for (let i = this.startYear; i <= this.endYear; i++) {
              arr.push(i + (this.hiddenUnits ? "" : this.yearText));
            }
            return arr;
          })(),
          onChange: (picker, value)=> {
            let year = parseInt(picker.cols[0].value),
              month = parseInt(picker.cols[1].value),
              day = parseInt(picker.cols[2].value);

            if ([4,6,9,11].indexOf(month) != -1 && day > 30) {
              picker.cols[2].setValue("30");
            };

            if(month === 2) {
              if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
                day > 29 && picker.cols[2].setValue("29");
              } else {
                day > 28 && picker.cols[2].setValue("28");
              }
            };
          }
        };

        months = {
          textAlign: "center",
          values: (()=> {
            let arr = [];
            for (let i = 1; i <= 12; i++) {
              arr.push(i);
            }
            return arr;
          })(),
          displayValues: (()=> {
            let arr = [];
            for (let i = 1; i <= 12; i++) {
              arr.push(i + (this.hiddenUnits ? "" : this.monthText));
            }
            return arr;
          })(),
          onChange: (picker, value)=> {
            let year = parseInt(picker.cols[0].value),
              month = parseInt(picker.cols[1].value),
              day = parseInt(picker.cols[2].value);

            if ([4,6,9,11].indexOf(month) != -1 && day > 30) {
              picker.cols[2].setValue("30");
            };

            if(month === 2) {
              if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
                day > 29 && picker.cols[2].setValue("29");
              } else {
                day > 28 && picker.cols[2].setValue("28");
              }
            };
          }
        };

        days = {
          textAlign: "center",
          values: (()=> {
            let arr = [];
            for (let i = 1; i <= 31; i++) {
              arr.push(i);
            }
            return arr;
          })(),
          displayValues: (()=> {
            let arr = [];
            for (let i = 1; i <= 31; i++) {
              arr.push(i + (this.hiddenUnits ? "" : this.dayText));
            }
            return arr;
          })(),
          onChange: (picker, value)=> {
            let year = parseInt(picker.cols[0].value),
              month = parseInt(picker.cols[1].value),
              day = parseInt(picker.cols[2].value);

            if ([4,6,9,11].indexOf(month) != -1 && day > 30) {
              picker.cols[2].setValue("30");
            };

            if(month === 2) {
              if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
                day > 29 && picker.cols[2].setValue("29");
              } else {
                day > 28 && picker.cols[2].setValue("28");
              }
            };
          }
        };

        if (this.withTime) {
          hours = {
            textAlign: "center",
            values: (()=> {
              let arr = [];
              for (let i = 0; i < 24; i++) {
                arr.push(i);
              }
              return arr;
            })(),
            displayValues: (()=> {
              let arr = [];
              for (let i = 0; i < 24; i++) {
                arr.push((i < 10 ? "0" + i : i + "") + (this.hiddenUnits ? "" : this.hourText));
              }
              return arr;
            })()
          };

          minutes = {
            textAlign: "center",
            values: (()=> {
              let arr = [];
              for (let i = 0; i < 60; i++) {
                arr.push(i);
              }
              return arr;
            })(),
            displayValues: (()=> {
              let arr = [];
              for (let i = 0; i < 60; i++) {
                arr.push((i < 10 ? "0" + i : i + "") + (this.hiddenUnits ? "" : this.minuteText));
              }
              return arr;
            })()
          };
        }

        opts.cols = this.withTime ? [years, months, days, hours, minutes] : [years, months, days];
      } else {
        // 排序
        this.dateOptions.sort((a, b) => {
          return b[this.sortKeyForYear] - a[this.sortKeyForYear];
        });
        let arr = {
          textAlign: "center",
          values: [],
          displayValues: [],
          width: "100%"
        };
        this.$util.each(this.dateOptions, t => {
          if (this.$util.isString(t)) {
            arr.values.push(t);
            arr.displayValues.push(this.withQuarter ? this.toQuarter(t) : t);
          } else {
            arr.values.push(t[this.optionValue]);
            arr.displayValues.push(
              this.withQuarter
                ? this.toQuarter(t[this.optionKey])
                : t[this.optionKey]
            );
          }
        });
        opts.cols = [arr];
      }
    },
    setValue(newVal) {
      // $input[0].f7Picker = this.picker;
      if (newVal != undefined && this.picker.getValue() != newVal) {
        this.picker.setValue(this.$util.buildArray(newVal));
        this.lastValue = newVal;
      }
    }
  },
  mounted() {
    const app = this.$f7;
    const $input = this.$$(this.$el).find("input");
    let opts = this.$util.extend({ inputEl: $input }, this.params || {});

    if (!this.options || this.options.length == 0) {
      this.dateOptions = [];
      // 不传options的情况下，默认加上
      if (this.withMonth) {
        for (let i = this.startYear; i <= this.endYear; i++) {
          /**
           *
           带年月的：[
              {key: "2020", value: [1,2,3]},
              {key: "2019", value: [1,2,3]},
              {key: "2018", value: [1,2,3]},
            ],
          */
          let item = {
            key: i + "", value: [1,2,3,4,5,6,7,8,9,10,11,12]
          };
          this.dateOptions.push(item);
        }
      }
    } else {
      this.dateOptions = this.options;
    }
    // 初始化操作
    this.init(opts);

    if (!opts.formatValue) {
      opts.formatValue = (values, displayValues) => {
        if (this.displayValue) {
          return displayValues;
        } else {
          return values;
        }
      };
    }

    this.picker = app.picker.create(opts);
    // 设置默认值
    if (this.withMonth) {
      this.picker.setValue([
        opts.cols[0].values[0],
        opts.cols[1].values[opts.cols[1].values.length - 1]
      ]);
      this.lastValue = this.picker.getValue();
    } else {
      this.picker.setValue([this.defaultDate.getFullYear()]);
      this.lastValue = this.picker.getValue();
    }

    this.picker.on("change", (picker, value, displayValue) => {
      this.$emit("input", value.join(" "));
      this.$emit("change", value, displayValue);
      if (this.required) {
        this.validatePicker();
      }
    });
    this.picker.on("closed", (picker, value, displayValue) => {
      if (this.picker.getValue() != this.lastValue) {
        this.$emit("submit", this.picker.getValue());
        this.lastValue = this.picker.getValue();
      }
    });
    // $input[0].f7Picker = this.picker;
    if (this.value != undefined && this.picker.getValue() != this.value) {
      this.picker.setValue(this.$util.buildArray(this.value));
      this.lastValue = this.value;
    }
  },
  beforeDestroy() {
    this.picker.destroy();
  }
};
</script>
<style scoped>
</style>

